﻿using System;
using Microsoft.Live;
using Newtonsoft.Json;

namespace WinLiveHelper.Wp7
{
	public class LiveConnectClientWrapper
	{
		#region Fields

		private const string DEFAULT_EVENTS = "me/events";
		private const string REFRESH_TOKEN_KEY = "Microsoft.Live.LiveAuthClient.RefreshToken";
		private const string SCOPE_KEY = "Microsoft.Live.LiveAuthClient.Scope";

		private LiveConnectClient _liveConnectClient;

		#endregion

		#region Construction

		private LiveConnectClientWrapper()
		{
		}

		#endregion

		#region Events

		public event EventHandler<PayloadEventArgs<Event>> EventCreated;
		private void OnEventCreated(PayloadEventArgs<Event> e)
		{
			var handler = EventCreated;
			if (handler != null) handler(this, e);
		}

		#endregion

		#region Properties

		private static LiveConnectClientWrapper _instance;
		public static LiveConnectClientWrapper Instance
		{
			get
			{
				if (_instance == null)
				{
					_instance = new LiveConnectClientWrapper();
				}
				return _instance;
			}
		}

		public bool IsInitialized { get; private set; }

		#endregion

		#region Public Methods

		public void Initialize(LiveConnectSession session)
		{
			if (IsInitialized)
				return;

			_liveConnectClient = new LiveConnectClient(session);
			_liveConnectClient.PostCompleted += ServiceCreateEventCompletedHandler;

			IsInitialized = true;
		}

		public void GetCalendarsAsync()
		{
			ValidateIsInitialized();

			_liveConnectClient.GetCompleted += ServiceGetCalendarsCompletedHandler;
			_liveConnectClient.GetAsync("/me/calendars");
		}

		public void GetCalendarAsync(string id)
		{
			ValidateIsInitialized();

			_liveConnectClient.GetCompleted += ServiceGetCalendarCompletedHandler;
			_liveConnectClient.GetAsync(id);
		}

		public void CreateCalendarAsync(Calendar calendar)
		{
			ValidateIsInitialized();

			_liveConnectClient.PostCompleted += ServiceCreateCalendarCompletedHandler;

			var serializedCalendar = JsonConvert.SerializeObject(calendar);

			_liveConnectClient.PostAsync("/me/calendars", serializedCalendar, null);
		}

		public void SubscribeToCalendarAsync(Calendar calendar)
		{
			ValidateIsInitialized();

			_liveConnectClient.PostCompleted += ServiceSubscribeToCalendarCompletedHandler;
		}

		public void UpdateCalendarAsync(Calendar calendar)
		{
			ValidateIsInitialized();

			_liveConnectClient.PutCompleted += ServiceUpdateCalendarCompletedHandler;
		}

		public void DeleteCalendarAsync(Calendar calendar)
		{
			ValidateIsInitialized();

			_liveConnectClient.DeleteCompleted += ServiceDeleteCalendarCompletedHandler;
		}

		public void CreateEventAsync(Event newEvent, string targetCalendar = "/me/events", object userState = null)
		{
			ValidateIsInitialized();

			var serializedEvent = JsonConvert.SerializeObject(newEvent);

			_liveConnectClient.PostAsync(targetCalendar, serializedEvent, userState);
		}

		public void GetContactsAsync()
		{
			ValidateIsInitialized();

			_liveConnectClient.GetCompleted += ServiceGetContactsHandler;
			_liveConnectClient.GetAsync("/me/contacts");
		}

		public void GetUserAsync(string userId)
		{
			ValidateIsInitialized();

			_liveConnectClient.GetCompleted += ServiceGetUserHandler;
			_liveConnectClient.GetAsync(userId);
		}

		#endregion

		#region Private Methods

		private void ValidateIsInitialized()
		{
			if (!IsInitialized)
				throw new InvalidOperationException("LiveConnectClientWrapper must be initialized before making service calls.");
		}

		private void ServiceGetCalendarsCompletedHandler(object sender, LiveOperationCompletedEventArgs e)
		{
			_liveConnectClient.GetCompleted -= ServiceGetCalendarsCompletedHandler;

			var c = JsonConvert.DeserializeObject<DataCollectionWrapper<Calendar>>(e.RawResult);
		}

		private void ServiceGetCalendarCompletedHandler(object sender, LiveOperationCompletedEventArgs e)
		{
			_liveConnectClient.GetCompleted -= ServiceGetCalendarCompletedHandler;

			var a = JsonConvert.DeserializeObject<Calendar>(e.RawResult);
		}

		private void ServiceCreateCalendarCompletedHandler(object sender, LiveOperationCompletedEventArgs e)
		{
			_liveConnectClient.PostCompleted -= ServiceCreateCalendarCompletedHandler;

			var newCalendar = JsonConvert.DeserializeObject<Calendar>(e.RawResult);
		}

		private void ServiceSubscribeToCalendarCompletedHandler(object sender, LiveOperationCompletedEventArgs e)
		{
			_liveConnectClient.PostCompleted -= ServiceSubscribeToCalendarCompletedHandler;

		}

		private void ServiceUpdateCalendarCompletedHandler(object sender, LiveOperationCompletedEventArgs e)
		{
			_liveConnectClient.PutCompleted -= ServiceUpdateCalendarCompletedHandler;

		}

		private void ServiceDeleteCalendarCompletedHandler(object sender, LiveOperationCompletedEventArgs e)
		{
			_liveConnectClient.DeleteCompleted -= ServiceDeleteCalendarCompletedHandler;

		}

		private void ServiceGetContactsHandler(object sender, LiveOperationCompletedEventArgs e)
		{
			_liveConnectClient.GetCompleted -= ServiceGetContactsHandler;

			var c = JsonConvert.DeserializeObject<DataCollectionWrapper<Contact>>(e.RawResult);
		}

		private void ServiceGetUserHandler(object sender, LiveOperationCompletedEventArgs e)
		{
			_liveConnectClient.GetCompleted -= ServiceGetUserHandler;

			var c = JsonConvert.DeserializeObject<Contact>(e.RawResult);
		}

		private void ServiceCreateEventCompletedHandler(object sender, LiveOperationCompletedEventArgs e)
		{
			var args = e.Error != null
			           	? new PayloadEventArgs<Event>(e.Error, e.UserState)
						: new PayloadEventArgs<Event>(JsonConvert.DeserializeObject<Event>(e.RawResult), e.UserState);

			OnEventCreated(args);
		}

		#endregion
	}
}